package com.androdro.bluenote.coolstruttin1588;
/**
 * Cool Struttin'
 * BlueMinor.java
 *
 * @author Hiroaki Sakuma <sakuma@androdro.com>
 * @version $Id$
 *
 * Copyright (C) androdro lab. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of the nor the names of its contributors may be used to
 *   endorse or promote products derived from this software without specific
 *   prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 */

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.net.http.AndroidHttpClient;
import android.os.Bundle;
import android.view.Display;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Toast;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;

import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.ListView;
import android.widget.LinearLayout;
import android.widget.BaseAdapter;

import com.androdro.bluenote.coolstruttin1588.adapter.*;

public abstract class BlueMinor
	extends
		ListView
	implements
		Runnable,
		CoolStruttin1588 {

	/**
   *
   */

	protected CoolStruttin root;

	private Context c;
	private Resources r;
	private BlueMinorAdapter adapter;
	private Thread t;
	private static Object lock;

	private float px = 0;
	private float py = 0;
	private boolean touchDown, moving, mIsMagneticFieldSensor, mIsAccelerometerSensor;


	public BlueMinor(CoolStruttin root) {

		super(root);
		this.root = root;
		lock = new Object();

		try {

			this.c = this.root.getApplicationContext();
			this.r = this.c.getResources();

			setBackgroundColor(Color.WHITE);

			this.adapter = new BlueMinorAdapter(this.root);
			this.adapter.setBlueMinor(this);
			setAdapter(this.adapter);

		} catch (Exception e) {
			Toast.makeText(this.c, e.toString() + "on " + getClass().toString() + " " + e.getStackTrace()[0].getMethodName(), Toast.LENGTH_LONG).show();
		}

	}


	@Override
	protected void onDraw(Canvas canvas) {

//System.out.println("onDraw");

		if (this.t == null) {

			this.t = new Thread(this);

			synchronized(lock) {
				this.t.start();
				try {
					lock.wait();
				} catch(InterruptedException ex) {
					ex.printStackTrace();
				}
				((BaseAdapter)getAdapter()).notifyDataSetChanged();
			}

		}

	}


	public void run() {

		Bitmap map = null;
//		HashMap<String, SippinAtBells.Status> result = new HashMap<String, SippinAtBells.Status>();
		ArrayList<SippinAtBells.Status> result = new ArrayList<SippinAtBells.Status>();
		AndroidHttpClient client;
		long time, last = 0;

		try {

			while(this.t != null && !this.root.isFinishing()) {

				synchronized(lock) {

					time = System.currentTimeMillis();
System.out.println("time = " + time + ", last = " + last + ", (time - last) = " + (time - last));

					if (time > last + 150 * 1000) {
						map = null;
					}

					if (map == null) {

System.out.println("map get" + getMapImagePath());

						HttpGet request = new HttpGet(getMapImagePath());
						client = AndroidHttpClient.newInstance(HTTP_USER_AGENT, this.c);

						try {

							map = client.execute(request, new ResponseHandler<Bitmap>() {
								@Override
								public Bitmap handleResponse(HttpResponse response)
									throws
										ClientProtocolException,
										IOException {
											switch(response.getStatusLine().getStatusCode()) {
												case HttpStatus.SC_OK:
													return BitmapFactory.decodeStream(response.getEntity().getContent());
												default:
													return null;
											}
								}

							});

						} finally {
							client.getConnectionManager().shutdown();
							client.close();
						}

						last = time;

						result = checkMap(map);
						this.adapter.setItems(result);

					}

					lock.notify();

				} //synchronized
				Thread.sleep(10000);

			} //while

		} catch (Exception e) {
			e.printStackTrace();
		}


	}


	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
			//this.holder.setFixedSize(w, h);
	}


	protected String getMapImagePath() {
		return this.root.getBackground().getHighwayImageURL(getMapName());
	}


	protected abstract String getMapName();


	protected abstract String getMapKind();


	protected ArrayList<SippinAtBells.Status> checkMap(Bitmap map) {

		JSONObject config = this.root.getConfig();
		HashMap<Integer, String> status = new HashMap<Integer, String>();
//		HashMap<String, SippinAtBells.Status> result = new HashMap<String, SippinAtBells.Status>();
		ArrayList<SippinAtBells.Status> result = new ArrayList<SippinAtBells.Status>();
		Paint p = new Paint();
		p.setAlpha(255);

		try {

			Iterator colorsi = config.getJSONObject("Body").getJSONObject(getMapKind()).getJSONObject(getMapName()).getJSONObject("Colors").keys();
			while(colorsi.hasNext()) {
				String k = colorsi.next().toString();
				status.put(Integer.parseInt(config.getJSONObject("Body").getJSONObject(getMapKind()).getJSONObject(getMapName()).getJSONObject("Colors").getString(k), 16), k);
			}

			Iterator checkpointsi = config.getJSONObject("Body").getJSONObject(getMapKind()).getJSONObject(getMapName()).getJSONObject("CheckPoints").keys();
			while(checkpointsi.hasNext()) {

				String k = checkpointsi.next().toString();

				JSONArray checkpoint = config.getJSONObject("Body").getJSONObject(getMapKind()).getJSONObject(getMapName()).getJSONObject("CheckPoints").getJSONObject(k).getJSONArray("Points");
				String name = config.getJSONObject("Body").getJSONObject(getMapKind()).getJSONObject(getMapName()).getJSONObject("CheckPoints").getJSONObject(k).getString("Name");
				String line = config.getJSONObject("Body").getJSONObject(getMapKind()).getJSONObject(getMapName()).getJSONObject("CheckPoints").getJSONObject(k).getString("Line");

				HashMap<String, SippinAtBells.Status> r = new HashMap<String, SippinAtBells.Status>();

				int l = checkpoint.length();
				for (int i = 0; i < l; i++) {

					int cx, cy, cx2, cy2;
					double ct;

					try {

						cx = (int)checkpoint.getJSONObject(i).getLong("x");
						cy = (int)checkpoint.getJSONObject(i).getLong("y");
						try {
							cx2 = (int)checkpoint.getJSONObject(i).getLong("x2");
							cy2 = (int)checkpoint.getJSONObject(i).getLong("y2");
						} catch (JSONException jsone) {
							cx2 = cx;
							cy2 = cy;
						}

						if (cx2 - cx != 0 && cy2 - cy != 0) {

							ct = (cy2 - cy) / (cx2 - cx);

							if (cx > cx2) {
								int tmp = cx; cx = cx2; cx2 = tmp;
								tmp = cy; cy = cy2; cy2 = tmp;
							}

							for (int xi = cx; xi <= cx2; xi++) {
								int yi = cy + (int)ct * (xi - cx);
								//System.out.println("xi=" + xi + "; yi=" + yi + "; color=x" + Integer.toHexString(map.getPixel(xi, yi) & 0x00fcfcfc) + ", " + name);

								int s = checkCondition(map.getPixel(xi, yi), status);
								switch(s) {
									case CONDITION_CLOSED:
									case CONDITION_ACCIDENT:
									case CONDITION_CONGESTION:
									case CONDITION_SNOW:
									case CONDITION_JAM:
									case CONDITION_OTHER:
									default:
										r.put(getMapName() + line + k + Integer.toString(s), SippinAtBells.getInstance().getFactory().generateStatus(s, line, name));
								}

							}


						} else {

							if (cx > cx2) {
								int tmp = cx; cx = cx2; cx2 = tmp;
							}

							if (cy > cy2) {
								int tmp = cy; cy = cy2; cy2 = tmp;
							}

							//System.out.println("x=" + cx + "; y=" + cy + "; x2=" + cx + "; y2=" + cy + "; color=x" + Integer.toHexString(map.getPixel(cx, cy) & 0x00fcfcfc) + ", " + name);

							for (int xi = cx; xi <= cx2; xi++) {
								for (int yi = cy; yi <= cy2; yi++) {

									int s = checkCondition(map.getPixel(xi, yi), status);
									switch(s) {
										case CONDITION_CLOSED:
										case CONDITION_ACCIDENT:
										case CONDITION_CONGESTION:
										case CONDITION_SNOW:
										case CONDITION_JAM:
										case CONDITION_OTHER:
										default:
											r.put(getMapName() + line + k + Integer.toString(s), SippinAtBells.getInstance().getFactory().generateStatus(s, line, name));
									}

								}
							}

						}

					} catch (JSONException jsone) {
					}

				} //for

				for (String k2 : r.keySet()) {
					result.add(r.get(k2));
				}

			}

			//System.out.println(result);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;

	}


	protected Integer checkCondition(int color, HashMap<Integer, String> status) {

		Integer decleasecolor = Integer.valueOf(color & 0x00fcfcfc);
		HashMap<Integer, String> decleasestatus = new HashMap<Integer, String>();

		for (Integer k : status.keySet()) {
			decleasestatus.put(k & 0xfcfcfc, status.get(k));
		}

		String s = decleasestatus.get(decleasecolor);

		if (s == null) {
			return 0;
		} else if (s.equals("closed")) {
			return CONDITION_CLOSED;
		} else if (s.equals("accident")) {
			return CONDITION_ACCIDENT;
		} else if (s.equals("congestion")) {
			return CONDITION_CONGESTION;
		} else if (s.equals("snow")) {
			return CONDITION_SNOW;
		} else if (s.equals("jam")) {
			return CONDITION_JAM;
		} else if (s.equals("other")) {
			return CONDITION_OTHER;
		} else {
			return 0;
		}

	}


}
